from django import forms
from django.conf import settings
from django.db import models
from django.utils import timezone




# 用户账号信息模型
class Users(models.Model):
    user_id = models.AutoField(primary_key=True)  # 自增主键，从1开始
    username = models.CharField(max_length=50, unique=True)  # 用户名称，添加唯一约束
    password = models.CharField(max_length=255,null=True, blank=True)  # 密码
    status = models.IntegerField(default=1)  #状态：1正常/2营养顾问/3禁用/6管理员/9删除
    email = models.EmailField(max_length=100, unique=True)  # 用户邮箱，添加唯一约束
    phone = models.CharField(max_length=30,unique=True)     #用户联系方式，添加唯一约束
    full_name = models.CharField(max_length=100, blank=True, null=True)  # 用户全名，允许为空
    GENDER_CHOICES = (
        ('male', '男'),
        ('female', '女'),
        ('other', '其他'),
        ('prefer_not_to_say', '不愿透露')
    )
    gender = models.CharField(
        max_length=20,
        choices=GENDER_CHOICES,
        default='prefer_not_to_say'
    )  # 性别字段，使用enum类型，默认不愿透露
    birth_date = models.DateField(blank=True, null=True)  # 生日字段，允许为空
    height_cm = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True)  # 身高，允许为空
    weight_kg = models.DecimalField(max_digits=6, decimal_places=2, blank=True, null=True)  # 体重，允许为空
    created_at = models.DateTimeField(default=timezone.now)  # 账户创建时间，使用Django的timezone
    updated_at = models.DateTimeField(auto_now=True)  # 最后更新时间，自动更新

    # 新增慢性病相关字段
    has_autoimmune_disease = models.BooleanField(default=False)  # 是否有自身免疫性疾病
    autoimmune_disease_type = models.CharField(max_length=100, blank=True, null=True)  # 自身免疫性疾病类型，允许为空
    has_hypertension = models.BooleanField(default=False)  # 是否有高血压
    has_diabetes = models.BooleanField(default=False)  # 是否有糖尿病
    DIABETES_TYPE_CHOICES = (
        ('no', '无'),
        ('type1', '1型糖尿病'),
        ('type2', '2型糖尿病'),
        ('gestational', '妊娠期糖尿病'),
        ('other', '其他')
    )
    diabetes_type = models.CharField(
        max_length=20,
        choices=DIABETES_TYPE_CHOICES,
        default='no'
    )  # 糖尿病类型
    has_hyperlipidemia = models.BooleanField(default=False)  # 是否有高血脂
    other_chronic_conditions = models.TextField(blank=True, null=True)  # 其他慢性病情况，允许为空

    # 新增目标达成次数字段
    achieved_goals_count = models.IntegerField(default=0, verbose_name="目标达成次数")
    diet_records_count = models.IntegerField(default=0, verbose_name="饮食记录总次数")

    def toDict(self):
        return {
            'id': self.user_id,
            'username': self.username,
            'password': self.password,
            'email': self.email,
            'phone':self.phone,
            'full_name': self.full_name,
            'gender': self.gender,
            'birth_date': self.birth_date,
            'height_cm': self.height_cm,
            'weight_kg': self.weight_kg,
            'created_at': self.created_at,
            'updated_at': self.updated_at,
            'has_autoimmune_disease': self.has_autoimmune_disease,
            'autoimmune_disease_type': self.autoimmune_disease_type,
            'has_hypertension': self.has_hypertension,
            'has_diabetes': self.has_diabetes,
            'diabetes_type': self.diabetes_type,
            'has_hyperlipidemia': self.has_hyperlipidemia,
            'other_chronic_conditions': self.other_chronic_conditions,
            'achieved_goals_count': self.achieved_goals_count,
            'diet_records_count': self.diet_records_count
        }

    class Meta:
        db_table = "users"  # 更改表名


#用户健康数据模型
class UserBodyRecords(models.Model):
    """用户健康数据表模型（删除多余的status字段）"""
    record_id = models.AutoField(primary_key=True)
    user = models.ForeignKey(
        Users,  # 关联自定义用户模型
        on_delete=models.CASCADE,
        related_name='body_records',
        db_column='user_id'
    )
    record_date = models.DateField()
    weight = models.DecimalField(
        max_digits=5, 
        decimal_places=2, 
        null=True, 
        blank=True,
    )  # 体重(kg)
    body_fat_percentage = models.DecimalField(
        max_digits=5, 
        decimal_places=2, 
        null=True, 
        blank=True,
    )  # 体脂率(%)
    muscle_mass = models.DecimalField(
        max_digits=5, 
        decimal_places=2, 
        null=True, 
        blank=True,
    )  # 肌肉量(kg)
    water_percentage = models.DecimalField(
        max_digits=5, 
        decimal_places=2, 
        null=True, 
        blank=True,
    )  # 水分率(%)
    bone_mass = models.DecimalField(
        max_digits=5, 
        decimal_places=2, 
        null=True, 
        blank=True,
    )  # 骨量(kg)
    blood_pressure_systolic = models.IntegerField(
        null=True, 
        blank=True,
    )  # 收缩压(mmHg)
    blood_pressure_diastolic = models.IntegerField(
        null=True, 
        blank=True,
    )  # 舒张压(mmHg)
    blood_sugar = models.DecimalField(
        max_digits=5, 
        decimal_places=2, 
        null=True, 
        blank=True,
    )  # 血糖(mmol/L)
    notes = models.TextField(
        null=True, 
        blank=True,
    )  # 备注信息
    
    def toDict(self):
        return{
            'record_id': self.record_id,
            'user': self.user,
            'record_date': self.record_date,
            'weight': self.weight,
            'body_fat_percentage': self.body_fat_percentage,
            'muscle_mass': self.muscle_mass,
            'water_percentage': self.water_percentage,
            'bone_mass': self.bone_mass,
            'blood_pressure_systolic': self.blood_pressure_systolic,
            'blood_pressure_diastolic': self.blood_pressure_diastolic,
            'blood_sugar': self.blood_sugar,
            'notes': self.notes
        }
    
    class Meta:
        db_table = 'user_body_records'
        ordering = ['-record_date']
        indexes = [
            models.Index(fields=['user', 'record_date']),
        ]
    
    def __str__(self):
        return f"{self.user.username}的身体记录 ({self.record_date.strftime('%Y-%m-%d')})"
    

#食物类别模型
class FoodCategories(models.Model):
    category_id = models.IntegerField(primary_key=True)
    category_name = models.CharField(max_length=100)
    # 自引用外键，related_name='children'表示子类别集合
    parent_id = models.ForeignKey('self', on_delete=models.SET_NULL, blank=True, null=True, 
                                  related_name='children', db_column='parent_id') # 明确指定关联数据库表中的字段名
    description = models.TextField(blank=True, null=True)

    def toDict(self):
        return {
            'category_id': self.category_id,
            'category_name': self.category_name,
            # 修复：返回父类别的ID（而非对象），避免序列化错误
            'parent_id': self.parent_id.category_id if self.parent_id else None,
            'description': self.description
        }

    class Meta:
        db_table = 'food_categories'

    def __str__(self):
        return self.category_name
    

#食物模型
class Foods(models.Model):
    food_id = models.AutoField(primary_key=True)
    food_name = models.CharField(max_length=100, unique=True)
    category = models.ForeignKey(
        FoodCategories, 
        on_delete=models.SET_NULL, 
        null=True, 
        blank=True, 
        db_column='category_id'  # 映射数据库的 category_id 字段
    )
    calories_per_100g = models.DecimalField(max_digits=8, decimal_places=2)
    protein_per_100g = models.DecimalField(max_digits=6, decimal_places=2)
    fat_per_100g = models.DecimalField(max_digits=6, decimal_places=2)
    carbs_per_100g = models.DecimalField(max_digits=6, decimal_places=2)
    fiber_per_100g = models.DecimalField(max_digits=6, decimal_places=2, default=0.00, blank=True)
    sugar_per_100g = models.DecimalField(max_digits=6, decimal_places=2, default=0.00, blank=True)
    sodium_per_100g = models.DecimalField(max_digits=6, decimal_places=2, default=0.00, blank=True)
    is_vegetarian = models.BooleanField(default=0)
    is_vegan = models.BooleanField(default=0)
    is_gluten_free = models.BooleanField(default=0)
    description = models.TextField(null=True, blank=True)
    image_url = models.CharField(max_length=255, null=True, blank=True)

    class Meta:
        db_table = "foods"
        indexes = [
            models.Index(fields=['category_id']),
        ]

    def toDict(self):
        return {
            'food_id': self.food_id,
            'food_name': self.food_name,
            'category_id': self.category.category_id,
            'calories_per_100g': self.calories_per_100g,
            'protein_per_100g': self.protein_per_100g,
            'fat_per_100g': self.fat_per_100g,
            'carbs_per_100g': self.carbs_per_100g,
            'fiber_per_100g': self.fiber_per_100g,
            'sugar_per_100g': self.sugar_per_100g,
            'sodium_per_100g': self.sodium_per_100g,
            'is_vegetarian': self.is_vegetarian,
            'is_vegan': self.is_vegan,
            'is_gluten_free': self.is_gluten_free,
            'description': self.description,
            'image_url': self.image_url
        }

    def __str__(self):
        return self.food_name
    


class DietPlan(models.Model):
    """饮食计划主表模型"""
    plan_id = models.AutoField(primary_key=True)
    plan_name = models.CharField(max_length=100, verbose_name="计划名称")  # 计划名称
    user = models.ForeignKey(
        'Users',  # 关联到用户表
        on_delete=models.CASCADE,
        related_name="diet_plans",  # 反向查询名：用户.plan_set -> 用户.diet_plans
        db_column="user_id",
        verbose_name="所属用户"
    )
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")  # 创建时间
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")  # 更新时间
    is_active = models.BooleanField(default=1, verbose_name="是否激活")  # 是否激活（默认激活）
    target_calories = models.IntegerField(null=True, blank=True, verbose_name="目标热量(大卡)")  # 目标热量
    protein_target = models.DecimalField(
        max_digits=6,
        decimal_places=2,
        null=True,
        blank=True,
        verbose_name="蛋白质目标(g)"
    )  # 蛋白质目标
    carbs_target = models.DecimalField(
        max_digits=6,
        decimal_places=2,
        null=True,
        blank=True,
        verbose_name="碳水目标(g)"
    )  # 碳水目标
    fat_target = models.DecimalField(
        max_digits=6,
        decimal_places=2,
        null=True,
        blank=True,
        verbose_name="脂肪目标(g)"
    )  # 脂肪目标
    notes = models.TextField(null=True, blank=True, verbose_name="计划备注")  # 计划备注

    def toDict(self):
        """转换为字典（便于序列化）"""
        return {
            'plan_id': self.plan_id,
            'plan_name': self.plan_name,
            'user_id': self.user.id,  # 存储用户ID而非对象（避免序列化错误）
            'user_name': self.user.username,
            'created_at': self.created_at.strftime("%Y-%m-%d %H:%M:%S"),  # 格式化时间
            'updated_at': self.updated_at.strftime("%Y-%m-%d %H:%M:%S"),
            'is_active': self.is_active,
            'target_calories': self.target_calories,
            'protein_target': float(self.protein_target) if self.protein_target else None,  # 转换Decimal为float
            'carbs_target': float(self.carbs_target) if self.carbs_target else None,
            'fat_target': float(self.fat_target) if self.fat_target else None,
            'notes': self.notes
        }

    class Meta:
        db_table = "diet_plans"  # 关联数据库表名
        ordering = ["-created_at"]  # 按创建时间倒序排列
        verbose_name = "饮食计划"
        verbose_name_plural = "饮食计划"

    def __str__(self):
        return f"{self.plan_name}（用户：{self.user.username}）"


class DietPlanDetail(models.Model):
    """饮食计划详情表模型（关联主表的子表）"""
    MEAL_TYPE_CHOICES = [
        ('早餐', '早餐'),
        ('上午加餐', '上午加餐'),
        ('午餐', '午餐'),
        ('下午加餐', '下午加餐'),
        ('晚餐', '晚餐'),
        ('睡前', '睡前'),
    ]  # 餐次类型选项

    detail_id = models.AutoField(primary_key=True)
    plan = models.ForeignKey(
        DietPlan,  # 关联到饮食计划主表
        on_delete=models.CASCADE,  # 主表记录删除时，子表同步删除
        related_name="details",  # 反向查询名：计划.details -> 获取所有餐次详情
        db_column="plan_id",
        verbose_name="所属计划"
    )
    meal_type = models.CharField(
        max_length=10,
        choices=MEAL_TYPE_CHOICES,
        verbose_name="餐次类型"
    )  # 餐次类型
    food = models.ForeignKey(
        'Foods',  # 关联到食物模型
        on_delete=models.CASCADE,
        db_column="food_id",
        verbose_name="食物"
    )  # 关联的食物
    quantity = models.DecimalField(
        max_digits=8,
        decimal_places=2,
        verbose_name="食物数量(克)"
    )  # 食物数量（克）
    meal_time = models.TimeField(null=True, blank=True, verbose_name="用餐时间")  # 用餐时间
    notes = models.TextField(null=True, blank=True, verbose_name="餐次备注")  # 餐次备注

    def toDict(self):
        """转换为字典（便于序列化）"""
        return {
            'detail_id': self.detail_id,
            'plan_id': self.plan.plan_id,  # 存储主表ID
            'meal_type': self.meal_type,
            'meal_type_display': self.get_meal_type_display(),  # 显示餐次类型中文
            'food_id': self.food.id,
            'food_name': self.food.food_name,  # 食物名称
            'quantity': float(self.quantity),  # 转换Decimal为float
            'meal_time': self.meal_time.strftime("%H:%M") if self.meal_time else None,  # 格式化时间
            'notes': self.notes
        }

    class Meta:
        db_table = "diet_plan_details"  # 关联数据库表名
        ordering = ["meal_type"]  # 按餐次类型排序
        verbose_name = "饮食计划详情"
        verbose_name_plural = "饮食计划详情"

    def __str__(self):
        return f"{self.plan.plan_name} - {self.get_meal_type_display()} - {self.food.food_name}"


# 饮食计划表单（用于前端数据验证和提交）
class DietPlanForm(forms.ModelForm):
    class Meta:
        model = DietPlan  # 关联的模型
        fields = ['plan_name', 'target_calories', 'protein_target', 
                 'carbs_target', 'fat_target', 'notes']  # 需要处理的字段
        widgets = {
            'notes': forms.Textarea(attrs={'rows': 3, 'class': 'form-control'}),
            'plan_name': forms.TextInput(attrs={'class': 'form-control'}),
            'target_calories': forms.NumberInput(attrs={'class': 'form-control'}),
            'protein_target': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}),
            'carbs_target': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}),
            'fat_target': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}),
        }  # 表单控件样式


class Recipes(models.Model):
    """食谱模型，对应recipes表"""
    recipe_id = models.AutoField(primary_key=True)
    recipe_name = models.CharField(max_length=200, unique=True)
    description = models.TextField(blank=True, null=True)
    prep_time = models.IntegerField(blank=True, null=True, help_text="准备时间（分钟）")
    cook_time = models.IntegerField(blank=True, null=True, help_text="烹饪时间（分钟）")
    total_calories = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True)
    is_suitable_for_chronic = models.BooleanField(default=False, help_text="是否适合慢性病患者")
    created_at = models.DateTimeField(default=timezone.now)
    updated_at = models.DateTimeField(auto_now=True)

    def toDict(self):
        return {
            'recipe_id': self.recipe_id,
            'recipe_name': self.recipe_name,
            'description': self.description,
            'prep_time': self.prep_time,
            'cook_time': self.cook_time,
            'total_calories': float(self.total_calories) if self.total_calories else None,
            'is_suitable_for_chronic': self.is_suitable_for_chronic,
            'created_at': self.created_at.strftime("%Y-%m-%d %H:%M:%S"),
            'updated_at': self.updated_at.strftime("%Y-%m-%d %H:%M:%S")
        }

    class Meta:
        db_table = "recipes"
        ordering = ['-created_at']

    def __str__(self):
        return self.recipe_name


class RecipeIngredients(models.Model):
    """食谱成分模型，对应recipe_ingredients表"""
    id = models.AutoField(primary_key=True)
    recipe = models.ForeignKey(
        Recipes,
        on_delete=models.CASCADE,
        related_name='ingredients',
        db_column='recipe_id'
    )
    food = models.ForeignKey(
        'Foods',  # 关联已存在的食物模型
        on_delete=models.CASCADE,
        db_column='food_id'
    )
    quantity = models.DecimalField(max_digits=8, decimal_places=2)
    unit = models.CharField(max_length=10, default='g')

    def toDict(self):
        return {
            'id': self.id,
            'recipe_id': self.recipe.recipe_id,
            'food_id': self.food.food_id,
            'food_name': self.food.food_name,  # 包含食物名称便于前端展示
            'quantity': float(self.quantity),
            'unit': self.unit
        }

    class Meta:
        db_table = "recipe_ingredients"
        indexes = [
            models.Index(fields=['recipe_id']),
            models.Index(fields=['food_id']),
        ]

    def __str__(self):
        return f"{self.recipe.recipe_name} - {self.food.food_name} ({self.quantity}{self.unit})"
    


# 用户饮食记录表模型
class UserDietRecords(models.Model):
    """用户饮食记录表模型，用于记录用户实际饮食情况"""
    MEAL_TYPE_CHOICES = [
        ('早餐', '早餐'),
        ('上午加餐', '上午加餐'),
        ('午餐', '午餐'),
        ('下午加餐', '下午加餐'),
        ('晚餐', '晚餐'),
        ('睡前', '睡前'),
    ]  # 餐次类型选项，与DietPlanDetail保持一致

    record_id = models.AutoField(primary_key=True)
    user = models.ForeignKey(
        Users,
        on_delete=models.CASCADE,
        related_name='diet_records',
        db_column='user_id'
    )  # 关联用户表
    food = models.ForeignKey(
        Foods,
        on_delete=models.CASCADE,
        db_column='food_id'
    )  # 关联食物表
    quantity = models.DecimalField(
        max_digits=8,
        decimal_places=2
    )  # 食物数量（克）
    record_time = models.DateTimeField(default=timezone.now)  # 记录时间（包含日期和具体时间）
    meal_type = models.CharField(
        max_length=10,
        choices=MEAL_TYPE_CHOICES
    )  # 餐次类型

    def toDict(self):
        """转换为字典，便于序列化和前端展示"""
        # 计算该记录对应的营养成分（基于100g含量和实际重量）
        quantity_ratio = self.quantity / 100
        return {
            'record_id': self.record_id,
            'user_id': self.user.user_id,
            'user_name': self.user.username,
            'food_id': self.food.food_id,
            'food_name': self.food.food_name,
            'quantity': float(self.quantity),
            'record_time': self.record_time.strftime("%Y-%m-%d %H:%M:%S"),
            'meal_type': self.meal_type,
            'meal_type_display': self.get_meal_type_display(),
            # 营养成分计算
            'calories': float(self.food.calories_per_100g * quantity_ratio),
            'protein': float(self.food.protein_per_100g * quantity_ratio),
            'fat': float(self.food.fat_per_100g * quantity_ratio),
            'carbs': float(self.food.carbs_per_100g * quantity_ratio),
            'sugar': float(self.food.sugar_per_100g * quantity_ratio),
            'sodium': float(self.food.sodium_per_100g * quantity_ratio)
        }

    class Meta:
        db_table = 'user_diet_records'
        ordering = ['-record_time']  # 按记录时间倒序排列
        indexes = [
            models.Index(fields=['user', 'record_time']),  # 便于按用户和时间查询
            models.Index(fields=['user', 'meal_type', 'record_time']),  # 便于按用户、餐次和时间查询
        ]
        verbose_name = "用户饮食记录"
        verbose_name_plural = "用户饮食记录"

    def __str__(self):
        return f"{self.user.username} {self.record_time.strftime('%Y-%m-%d')} {self.get_meal_type_display()}: {self.food.food_name} ({self.quantity}g)"



class NutritionistAdvice(models.Model):
    """营养顾问建议模型，用于管理营养顾问给用户的建议及反馈状态"""
    # 状态选项：待处理、已处理、已反馈
    STATUS_CHOICES = [
        ('待处理', '待处理'),
        ('已处理', '已处理'),
        ('已反馈', '已反馈'),
    ]
    
    advice_id = models.AutoField(primary_key=True)
    user = models.ForeignKey(
        Users,
        on_delete=models.CASCADE,
        related_name='nutritionist_advices',
        db_column='user_id'
    )  # 关联接收建议的用户
    nutritionist = models.ForeignKey(
        Users,
        on_delete=models.CASCADE,  # 数据库定义为NOT NULL，使用CASCADE确保引用完整性
        related_name='given_advices',
        db_column='nutritionist_id'
    )  # 关联提供建议的营养顾问
    advice_content = models.TextField(verbose_name="建议内容")  # 建议具体内容
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")  # 记录创建时间
    advice_date = models.DateField(verbose_name="建议日期")  # 建议针对的日期
    status = models.CharField(
        max_length=10,
        choices=STATUS_CHOICES,
        default='待处理'
    )  # 建议处理状态

    def toDict(self):
        """转换为字典，便于序列化和前端展示"""
        return {
            'advice_id': self.advice_id,
            'user_id': self.user.user_id,
            'user_name': self.user.username,
            'nutritionist_id': self.nutritionist.user_id,
            'nutritionist_name': self.nutritionist.username,
            'advice_content': self.advice_content,
            'created_at': self.created_at.strftime("%Y-%m-%d %H:%M:%S"),
            'advice_date': self.advice_date.strftime("%Y-%m-%d"),
            'status': self.status,
            'status_display': self.get_status_display()  # 显示状态的中文名称
        }

    class Meta:
        db_table = 'nutritionist_advice'
        ordering = ['-advice_date', '-created_at']  # 按建议日期和创建时间倒序排列
        indexes = [
            models.Index(fields=['user_id']),  # 数据库已定义的索引
            models.Index(fields=['nutritionist_id']),  # 便于按营养顾问查询
            models.Index(fields=['status']),  # 便于按状态筛选
            models.Index(fields=['advice_date']),  # 便于按建议日期查询
        ]
        verbose_name = "营养顾问建议"
        verbose_name_plural = "营养顾问建议"

    def __str__(self):
        return f"{self.nutritionist.username}给{self.user.username}的建议（{self.advice_date.strftime('%Y-%m-%d')}）"
    

class RecommendationRecords(models.Model):
    """推荐记录模型，对应recommendation_records表"""
    # 推荐类型选项
    RECOMMENDATION_TYPE_CHOICES = [
        ('饮食计划', '饮食计划'),
        ('食物推荐', '食物推荐'),
        ('食谱', '食谱'),
    ]
    
    # 推荐依据选项
    BASED_ON_CHOICES = [
        ('身体数据', '身体数据'),
        ('饮食偏好', '饮食偏好'),
        ('健康目标', '健康目标'),
        ('综合', '综合'),
    ]
    
    recommendation_id = models.AutoField(primary_key=True)
    user = models.ForeignKey(
        Users,
        on_delete=models.CASCADE,
        related_name='recommendation_records',
        db_column='user_id'
    )  # 关联用户表
    recommendation_time = models.DateTimeField(
        default=timezone.now,
        null=True,
        blank=True
    )  # 推荐时间，默认当前时间
    recommendation_type = models.CharField(
        max_length=10,
        choices=RECOMMENDATION_TYPE_CHOICES
    )  # 推荐类型
    based_on = models.CharField(
        max_length=10,
        choices=BASED_ON_CHOICES
    )  # 推荐依据
    content = models.TextField()  # 推荐内容
    is_accepted = models.BooleanField(
        null=True,
        blank=True
    )  # 是否接受推荐，null表示未反馈
    feedback = models.TextField(
        null=True,
        blank=True
    )  # 反馈内容
    
    def toDict(self):
        """转换为字典，便于序列化和前端展示"""
        return {
            'recommendation_id': self.recommendation_id,
            'user_id': self.user.user_id,
            'user_name': self.user.username,
            'recommendation_time': self.recommendation_time.strftime("%Y-%m-%d %H:%M:%S") if self.recommendation_time else None,
            'recommendation_type': self.recommendation_type,
            'recommendation_type_display': self.get_recommendation_type_display(),
            'based_on': self.based_on,
            'based_on_display': self.get_based_on_display(),
            'content': self.content,
            'is_accepted': self.is_accepted,
            'feedback': self.feedback
        }
    
    class Meta:
        db_table = 'recommendation_records'
        ordering = ['-recommendation_time']  # 按推荐时间倒序排列
        indexes = [
            models.Index(fields=['user_id']),  # 已定义的用户ID索引
            models.Index(fields=['recommendation_type']),  # 按推荐类型查询索引
            models.Index(fields=['based_on']),  # 按推荐依据查询索引
            models.Index(fields=['is_accepted']),  # 按接受状态查询索引
        ]
        verbose_name = "推荐记录"
        verbose_name_plural = "推荐记录"
    
    def __str__(self):
        return f"{self.user.username}的{self.get_recommendation_type_display()}推荐（{self.recommendation_time.strftime('%Y-%m-%d') if self.recommendation_time else ''}）"
    


class UserPreferences(models.Model):
    """用户偏好模型，记录用户对食物或食物类别的偏好程度"""
    PREFERENCE_LEVEL_CHOICES = [
        ('非常喜欢', '非常喜欢'),
        ('喜欢', '喜欢'),
        ('一般', '一般'),
        ('不喜欢', '不喜欢'),
        ('非常不喜欢', '非常不喜欢'),
    ]  # 偏好程度选项

    preference_id = models.AutoField(primary_key=True)
    user = models.ForeignKey(
        Users,
        on_delete=models.CASCADE,
        related_name='preferences',
        db_column='user_id'
    )  # 关联用户表
    preferred_category = models.ForeignKey(
        FoodCategories,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='preferred_by',
        db_column='preferred_category_id'
    )  # 关联食物类别表（可为空）
    preferred_food = models.ForeignKey(
        Foods,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='preferred_by',
        db_column='preferred_food_id'
    )  # 关联食物表（可为空）
    preference_level = models.CharField(
        max_length=10,
        choices=PREFERENCE_LEVEL_CHOICES,
        default='一般'
    )  # 偏好程度

    def toDict(self):
        """转换为字典，便于序列化和前端展示"""
        return {
            'preference_id': self.preference_id,
            'user_id': self.user.user_id,
            'user_name': self.user.username,
            'preferred_category_id': self.preferred_category.category_id if self.preferred_category else None,
            'preferred_category_name': self.preferred_category.category_name if self.preferred_category else None,
            'preferred_food_id': self.preferred_food.food_id if self.preferred_food else None,
            'preferred_food_name': self.preferred_food.food_name if self.preferred_food else None,
            'preference_level': self.preference_level,
            'preference_level_display': self.get_preference_level_display()
        }

    class Meta:
        db_table = 'user_preferences'
        indexes = [
            models.Index(fields=['user_id']),
            models.Index(fields=['preferred_category_id']),
            models.Index(fields=['preferred_food_id']),
        ]

    def __str__(self):
        target = self.preferred_food.food_name if self.preferred_food else \
                 self.preferred_category.category_name if self.preferred_category else "未知"
        return f"{self.user.username}对{target}的偏好：{self.get_preference_level_display()}"
    


class UserFeedbackfeedback(models.Model):
    """用户反馈模型，用于记录用户对系统的各类反馈信息"""
    # 反馈类型选项
    FEEDBACK_TYPE_CHOICES = [
        ('食谱建议', '食谱建议'),
        ('系统功能', '系统功能'),
        ('数据错误', '数据错误'),
        ('其他', '其他'),
    ]
    
    feedback_id = models.AutoField(primary_key=True)
    user = models.ForeignKey(
        Users,
        on_delete=models.CASCADE,
        related_name='feedbacks',
        db_column='user_id'
    )  # 关联提交反馈的用户
    feedback_type = models.CharField(
        max_length=10,
        choices=FEEDBACK_TYPE_CHOICES,
    )  # 反馈类型
    content = models.TextField(verbose_name="反馈内容")  # 反馈具体内容
    related_recipe = models.ForeignKey(
        Recipes,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='related_feedbacks',
        db_column='related_recipe_id',
    )  # 关联的食谱（可为空）
    created_at = models.DateTimeField(
        default=timezone.now,
    )  # 反馈创建时间
    is_resolved = models.BooleanField(
        default=False,
    )  # 反馈是否已解决
    reply = models.TextField(
        null=True,
        blank=True,
    )  # 对反馈的回复内容

    def toDict(self):
        """转换为字典，便于序列化和前端展示"""
        return {
            'feedback_id': self.feedback_id,
            'user_id': self.user.user_id,
            'user_name': self.user.username,
            'feedback_type': self.feedback_type,
            'feedback_type_display': self.get_feedback_type_display(),
            'content': self.content,
            'related_recipe_id': self.related_recipe.recipe_id if self.related_recipe else None,
            'related_recipe_name': self.related_recipe.recipe_name if self.related_recipe else None,
            'created_at': self.created_at.strftime("%Y-%m-%d %H:%M:%S"),
            'is_resolved': self.is_resolved,
            'reply': self.reply
        }

    class Meta:
        db_table = 'user_feedback'
        ordering = ['-created_at']  # 按创建时间倒序排列
        indexes = [
            models.Index(fields=['user_id']),
            models.Index(fields=['related_recipe_id']),
            models.Index(fields=['is_resolved']),  # 便于按解决状态筛选
        ]

    def __str__(self):
        return f"{self.user.username}的{self.get_feedback_type_display()}反馈（{self.created_at.strftime('%Y-%m-%d')}）"



class SystemNotice(models.Model):
    """系统通知模型，用于存储系统更新相关通知"""
    NOTICE_TYPE_CHOICES = [
        ('system_update', '系统更新'),
        ('feature_announcement', '功能公告'),
        ('maintenance', '维护通知'),
        ('other', '其他'),
    ]  # 通知类型选项

    notice_id = models.AutoField(primary_key=True, verbose_name="通知ID")
    title = models.CharField(max_length=255, verbose_name="通知标题")
    content = models.TextField(verbose_name="通知详细内容")
    notice_type = models.CharField(
        max_length=20,
        choices=NOTICE_TYPE_CHOICES,
        default='other',
        verbose_name="通知类型"
    )
    is_important = models.BooleanField(default=False, verbose_name="是否为重要通知")
    publish_time = models.DateTimeField(default=timezone.now, verbose_name="发布时间")
    expire_time = models.DateTimeField(null=True, blank=True, verbose_name="过期时间")
    is_active = models.BooleanField(default=True, verbose_name="是否启用显示")
    created_at = models.DateTimeField(default=timezone.now, verbose_name="记录创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="记录更新时间")

    def toDict(self):
        """转换为字典，便于序列化和前端展示"""
        return {
            'notice_id': self.notice_id,
            'title': self.title,
            'content': self.content,
            'notice_type': self.notice_type,
            'notice_type_display': self.get_notice_type_display(),
            'is_important': self.is_important,
            'publish_time': self.publish_time.strftime("%Y-%m-%d %H:%M:%S"),
            'expire_time': self.expire_time.strftime("%Y-%m-%d %H:%M:%S") if self.expire_time else None,
            'is_active': self.is_active,
            'created_at': self.created_at.strftime("%Y-%m-%d %H:%M:%S"),
            'updated_at': self.updated_at.strftime("%Y-%m-%d %H:%M:%S")
        }

    class Meta:
        db_table = "system_notice"
        ordering = ['-publish_time']  # 按发布时间倒序排列
        indexes = [
            models.Index(fields=['publish_time'], name='idx_publish_time'),
            models.Index(fields=['is_active'], name='idx_is_active'),
        ]

    def __str__(self):
        return f"{self.title}（{self.get_notice_type_display()}）"